﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using Xoohoo.Extensions;
using Xoohoo.Infrastructure;
using Xoohoo.Models;
using Xoohoo.Models.InputModels;
using Xoohoo.Models.ViewModels;
using Xoohoo.Services;

namespace Xoohoo.Modules.Membership.Controllers
{
    public class MembershipController : Controller,IModuleSubMenu
    {
        private readonly IUserService _userService;
        private readonly IUserGroupService _userGroupService;
        private readonly IRoleService _roleService;
        private readonly IPermissionService _permissionService;
        private readonly XoohooContext _context;

        public MembershipController(IUserService userService, IUserGroupService userGroupService, IRoleService roleService, IPermissionService permissionService, XoohooContext context)
        {
            this._userService = userService;
            this._userGroupService = userGroupService;
            this._permissionService = permissionService;
            this._roleService = roleService;
            this._context = context;
        }

        #region IModuleSubMenu Members

        public XoohooViewModelItem<Xoohoo.Models.ModuleSubMenuItemList> SubMenu()
        {
            ModuleSubMenuItemList sm = new ModuleSubMenuItemList("用户管理") { 
                 new ModuleSubMenuItemSingle{ Title="用户信息管理",MenuLevel=1,Permission="用户信息管理"}
                ,new ModuleSubMenuItemSingle{ Title="用户信息列表",MenuLevel=2,Permission="用户信息管理",ContentRouteName="Admin.Membership.User.UserList"}
                ,new ModuleSubMenuItemSingle{ Title="用户信息添加",MenuLevel=2,Permission="用户信息管理",ContentRouteName="Admin.Membership.User.UserAdd"}
                ,new ModuleSubMenuItemSingle{ Title="用户组管理",MenuLevel=1,Permission="用户组管理"}
                ,new ModuleSubMenuItemSingle{ Title="用户组列表",MenuLevel=2,Permission="用户组管理",ContentRouteName="Admin.Membership.User.UserGroupList"}
                ,new ModuleSubMenuItemSingle{ Title="用户组添加",MenuLevel=2,Permission="用户组管理",ContentRouteName="Admin.Membership.User.UserGroupAdd"}
                ,new ModuleSubMenuItemSingle{ Title="角色管理",MenuLevel=1,Permission="角色管理"}
                ,new ModuleSubMenuItemSingle{ Title="角色列表",MenuLevel=2,Permission="角色管理",ContentRouteName="Admin.Membership.User.RoleList"}
                ,new ModuleSubMenuItemSingle{ Title="角色添加",MenuLevel=2,Permission="角色管理",ContentRouteName="Admin.Membership.User.RoleAdd"}
                ,new ModuleSubMenuItemSingle{ Title="权限管理",MenuLevel=1,Permission="权限管理"}
                ,new ModuleSubMenuItemSingle{ Title="权限列表",MenuLevel=2,Permission="权限管理",ContentRouteName="Admin.Membership.User.PermissionList"}

//权限的添加、编辑（保存）、删除（保存）、移动由系统控制，要杜绝手工操作，下面的菜单主要用于调试模式
#if DEBUG
                ,new ModuleSubMenuItemSingle{ Title="权限添加",MenuLevel=2,Permission="权限管理",ContentRouteName="Admin.Membership.User.PermissionAdd"}
#endif
            };
            sm.RemoveByPermission(_context.User);
            return new XoohooViewModelItem<ModuleSubMenuItemList>(sm);
        }

        #endregion

        #region 用户管理

        public object UserList(UserSearchCriteria criteria, PagingInfo pageingInfo)
        {
            //用户信息列表
            IPagedList<UserBasic> users = _userService.GetList(criteria, pageingInfo);
            var xvm = new XoohooViewModelItem<IPagedList<UserBasic>>(users);

            //搜索条件
            xvm.AddModelItem(criteria);

            //用户组列表
            var userGroups = _userGroupService.GetList();
            ProjectUserGroups(userGroups);
            SelectList slUserGroup = new SelectList(userGroups, "UserGroupID", "UserGroupName", criteria.UserGroupID);
            xvm.AddModelItem("UserGroups", slUserGroup);

            //用户状态
            #region
            //var statusCollection = from e in typeof(UserStatus).GetFields()
            //                       where e.FieldType.IsEnum
            //                       select new
            //                       {
            //                           Value = e.Name
            //                       };
            //var statusCollection = from e in Enum.GetNames(typeof(UserStatus))
            //                       select new
            //                       {
            //                           Value = e
            //                       };
            //var statusCollection = from e in Enum.GetNames(typeof(UserStatus))
            //                       select new
            //                       {
            //                           Value = e,
            //                           Text = ((UserStatus)Enum.Parse(typeof(UserStatus), e)).ToChineseString()
            //                       };
            //var statusCollection = from e in Enum.GetValues(typeof(UserStatus)).Cast<byte>()
            //                       select new
            //                       {
            //                           Value = (UserStatus)e
            //                       };
            //var statusCollection = from e in Enum.GetValues(typeof(UserStatus)).Cast<UserStatus>()
            //                       select new
            //                       {
            //                           Value = e
            //                       };
            var statusCollection = from e in Enum.GetValues(typeof(UserStatus)).Cast<UserStatus>()
                                   select new
                                   {
                                       Value = e,
                                       Text = e.ToChinese()
                                   };
            #endregion

            SelectList slUserStatus = new SelectList(statusCollection, "Value", "Text", criteria.Status);
            xvm.AddModelItem("UserStatus", slUserStatus);

            //每页显示条数
            var pageSize = new List<object>
            {
              new{PageSize=10,PageSizeText="10条/页"},
              new{PageSize=20,PageSizeText="20条/页"},
              new{PageSize=50,PageSizeText="50条/页"},
              new{PageSize=100,PageSizeText="100条/页"}
            };

            SelectList slPageSize = new SelectList(pageSize, "PageSize", "PageSizeText", pageingInfo.Size);
            xvm.AddModelItem("PageSize", slPageSize);

            return xvm;
        }
        public object UserAddOrEdit(int? userID)
        {
            //用户组
            var userGroups = _userGroupService.GetList();
            ProjectUserGroups(userGroups);

            //获取角色列表
            var roles = _roleService.GetList();

            //获取权限树
            var permissions = _permissionService.GetList();
            ProjectPermissions(permissions);

            //用户状态
            #region
            //var statusCollection = from e in typeof(UserStatus).GetFields()
            //                       where e.FieldType.IsEnum
            //                       select new
            //                       {
            //                           Value = e.Name
            //                       };
            //var statusCollection = from e in Enum.GetNames(typeof(UserStatus))
            //                       select new
            //                       {
            //                           Value = e
            //                       };
            //var statusCollection = from e in Enum.GetNames(typeof(UserStatus))
            //                       select new
            //                       {
            //                           Value = e,
            //                           Text = ((UserStatus)Enum.Parse(typeof(UserStatus), e)).ToChineseString()
            //                       };
            //var statusCollection = from e in Enum.GetValues(typeof(UserStatus)).Cast<byte>()
            //                       select new
            //                       {
            //                           Value = (UserStatus)e
            //                       };
            //var statusCollection = from e in Enum.GetValues(typeof(UserStatus)).Cast<UserStatus>()
            //                       select new
            //                       {
            //                           Value = e
            //                       };
            var statusCollection = from e in Enum.GetValues(typeof(UserStatus)).Cast<UserStatus>()
                                   select new
                                   {
                                       Value = e,
                                       Text = e.ToChinese()
                                   };
            #endregion

            var xvm = new XoohooViewModelItem<User>(null);
            //特定角色
            SelectList slRoles = new SelectList(roles, "RoleID", "RoleName");
            xvm.AddModelItem("Roles", slRoles);
            //特定权限
            xvm.AddModelItem("Permissions", permissions);

            if (userID.HasValue)
            {
                //用户信息
                var user = _userService.GetItem(userID.Value);
                if (user == null) return null;
                xvm.Item = user;

                //用户组
                SelectList slUserGroup = new SelectList(userGroups, "UserGroupID", "UserGroupName", user.UserGroup.UserGroupID);
                xvm.AddModelItem("UserGroups", slUserGroup);
                //用户状态
                SelectList slUserStatus = new SelectList(statusCollection, "Value", "Text", user.Status);
                xvm.AddModelItem("UserStatus", slUserStatus);

                return xvm;
            }
            else
            {

                SelectList slUserGroup = new SelectList(userGroups, "UserGroupID", "UserGroupName");
                xvm.AddModelItem("UserGroups", slUserGroup);
                SelectList slUserStatus = new SelectList(statusCollection, "Value", "Text", Xoohoo.Models.UserStatus.Normal);
                xvm.AddModelItem("UserStatus", slUserStatus);

                return xvm;
            }
        }
        [HttpPost]
        public object UserAddSave(UserInputAdd userInput, string returnUrl)
        {
            var prompt = new PromptViewModel("用户编辑");
            var xvm = new XoohooViewModelItem<PromptViewModel>(prompt);
            if (!TryValidateModel(userInput))
            { 
                prompt.AddModelErrors(ModelState);
                return View("Prompt", xvm);
            }

            ModelResult modelResult = _userService.SaveAdd(userInput);
            return CreateUserSaveResult(modelResult, returnUrl);
        }
        [HttpPost]
        public object UserEditSave(UserInputEdit userInput, string returnUrl)
        {
            var prompt = new PromptViewModel("用户编辑");
            var xvm = new XoohooViewModelItem<PromptViewModel>(prompt);
            if (!TryValidateModel(userInput))
            { 
                prompt.AddModelErrors(ModelState);
                return View("Prompt", xvm);
            }

            ModelResult modelResult = _userService.SaveEdit(userInput);
            return CreateUserSaveResult(modelResult,returnUrl);
        }
        public object UserRemove(int userID, string returnUrl)
        {
            if (_userService.Remove(userID))
            {
                if (!String.IsNullOrEmpty(returnUrl))
                    return Redirect(returnUrl);
                else
                    return RedirectToAction("UserList");
            }
            else
            {
                var prompt = new PromptViewModel("用户删除");
                prompt.AddMessage("删除失败，请确认该用户存在并且不处于删除状态！");

                var xvm = new XoohooViewModelItem<PromptViewModel>(prompt);
                return View("Prompt",xvm);
            }

        }
        public object UserChangeStatus(int userID, UserStatus status, string returnUrl)
        {
            bool result =  _userService.ChangeStatus(userID, status);
            if (Request.IsAjaxRequest())
            {
                return Json(new { Result = result }, JsonRequestBehavior.AllowGet);
            }
            else
            {
                if (!String.IsNullOrEmpty(returnUrl))
                    return Redirect(returnUrl);
                else
                    return RedirectToAction("UserList");
            }
        }
        
        #endregion

        #region 用户组管理

        public object UserGroupList()
        {
            var userGroups = _userGroupService.GetList();
            ProjectUserGroups(userGroups);
            return new XoohooViewModelItem<IEnumerable<UserGroup>>(userGroups);
        }
        public object UserGroupEdit(Guid userGroupID)
        {
            var xvm = new XoohooViewModelItem<UserGroupInput>();

            //当前用户组信息
            var userGroup = _userGroupService.GetItem(userGroupID);
            xvm.Item = UserGroupInput.FromUserGroup(userGroup);

            //角色列表
            var roles = _roleService.GetList();
            xvm.AddModelItem("Roles", roles);

            //获取用户组树
            var userGroups = CreateUserGroupTreeForAddOrEdit(userGroupID);
            //父用户组下拉列表
            SelectList sl = new SelectList(userGroups, "UserGroupID", "UserGroupName", userGroup.ParentID);
            xvm.AddModelItem("UserGroups", sl);


            return View("UserGroupAddOrEdit", xvm);
        }
        public object UserGroupAdd(Guid? parentID)
        {
            var xvm = new XoohooViewModelItem<UserGroupInput>();

            var userGroups = CreateUserGroupTreeForAddOrEdit(null);
            SelectList sl = new SelectList(userGroups, "UserGroupID", "UserGroupName", parentID);
            xvm.AddModelItem("UserGroups", sl);

            //角色列表
            var roles = _roleService.GetList();
            xvm.AddModelItem("Roles", roles);

            return View("UserGroupAddOrEdit", xvm);
        }
        public object UserGroupRemove(Guid userGroupID)
        {
            if (_userGroupService.Remove(userGroupID))
                return RedirectToAction("UserGroupList");
            else
            {
                var prompt = new PromptViewModel("用户组管理");
                prompt.AddMessage("删除失败，当前用户组下有子用户组！");

                var xvm = new XoohooViewModelItem<PromptViewModel>(prompt);
                return View("Prompt",xvm);
            }
        }
        public object UserGroupMove(Guid userGroupID, MovingTarget target)
        {
            _userGroupService.Move(userGroupID, target);

            return RedirectToAction("UserGroupList");
        }
        [HttpPost]
        public object UserGroupSave(UserGroupInput userGroupInput)
        {
            PromptViewModel prompt = new PromptViewModel("用户组编辑");
            XoohooViewModelItem<PromptViewModel> xvm = new XoohooViewModelItem<PromptViewModel>(prompt);
            if (!TryValidateModel(userGroupInput))
            {
                var addOrEditXVM = new XoohooViewModelItem<UserGroupInput>(userGroupInput);
                //角色列表
                var roles = _roleService.GetList();
                addOrEditXVM.AddModelItem("Roles", roles);

                //获取用户组树
                var userGroups = CreateUserGroupTreeForAddOrEdit(userGroupInput.UserGroupID);
                SelectList sl = new SelectList(userGroups, "UserGroupID", "UserGroupName", userGroupInput.ParentID);
                addOrEditXVM.AddModelItem("UserGroups", sl);

                return View("UserGroupAddOrEdit", addOrEditXVM);
                //prompt.AddModelErrors(ModelState);
                //return View("Prompt", xvm);
            }
            ModelResult modelResult = _userGroupService.Save(userGroupInput);

            if (modelResult.IsValid)
            {
                return RedirectToAction("UserGroupList");
            }
            else
            {
                prompt.AddModelErrors(modelResult.Errors);
                return View("Prompt",xvm);
            }

        }

        #endregion

        #region 角色管理
        public object RoleList()
        {
            IEnumerable<RoleBasic> roles = _roleService.GetList();
            return new XoohooViewModelItem<IEnumerable<RoleBasic>>(roles);
        }
        public object RoleAddOrEdit(Guid? roleID)
        {
            var xvm = new XoohooViewModelItem<RoleInput>();
            //如果roleID不为空获取Role
            if (roleID.HasValue)
            {
                Role role = _roleService.GetItem(roleID.Value);
                if (role == null) return null;
                xvm.Item = RoleInput.FromRole(role);
            }
            //获取权限树
            var permissions = _permissionService.GetList();
            ProjectPermissions(permissions);
            xvm.AddModelItem("Permissions", permissions);

            return xvm;
        }
        [HttpPost]
        public object RoleSave(RoleInput roleInput)
        {
            var prompt = new PromptViewModel("角色编辑");
            var xvm = new XoohooViewModelItem<PromptViewModel>(prompt);
            if (!TryValidateModel(roleInput))
            {
                var andOrEditXVM = new XoohooViewModelItem<RoleInput>(roleInput);
                var permissions = _permissionService.GetList();
                ProjectPermissions(permissions);
                andOrEditXVM.AddModelItem("Permissions", permissions);
                return View("RoleAddOrEdit", andOrEditXVM);
            }
            ModelResult modelResult = _roleService.Save(roleInput);
            if (modelResult.IsValid)
            {
                return RedirectToAction("RoleList");
            }
            else
            {
                prompt.AddModelErrors(modelResult.Errors);
                return View("Prompt",xvm);
            }
        }
        public object RoleRemove(Guid roleID)
        {
            if (_roleService.Remove(roleID))
                return RedirectToAction("RoleList");
            else
            {
                var prompt = new PromptViewModel("权限管理");
                prompt.AddMessage("删除失败，未知错误！");

                var xvm = new XoohooViewModelItem<PromptViewModel>(prompt);
                return View("Prompt",xvm);
            }
        }
        public object RoleMove(Guid roleID, MovingTarget target)
        {
            _roleService.Move(roleID, target);

            return RedirectToAction("RoleList");
        }
        #endregion

        #region 权限管理

        public object PermissionList()
        {
            List<Permission> permissions = _permissionService.GetList();
            ProjectPermissions(permissions);
            return new XoohooViewModelItem<IEnumerable<Permission>>(permissions);
        }
        //权限的添加、编辑、删除由系统控制，要杜绝手工操作，下面的Action主要用于调试模式
#if DEBUG
        public object PermissionEdit(Guid permissionID)
        {
            //获取权限树
            var permissions = _permissionService.GetList().ToList();
            var permission = (from p in permissions where p.PermissionID == permissionID select p).FirstOrDefault();
            if (permission == null) return null;

            var xvm = new XoohooViewModelItem<PermissionInput>(permission.ToModel<PermissionInput>());
            xvm.AddModelItem(permission);

            //去除当前节点的子树(包括当前节点)
            RemoveChildren(permissions, permissionID);
            ProjectPermissions(permissions);
            SelectList sl = new SelectList(permissions, "PermissionID", "PermissionName", permission.ParentID);
            xvm.AddModelItem("Permissions", sl);

            return View("PermissionAddOrEdit", xvm);
        }
        public object PermissionAdd(Guid? parentID)
        {
            var xvm = new XoohooViewModelItem<PermissionInput>();
            var permissions = _permissionService.GetList();
            ProjectPermissions(permissions);
            SelectList sl = new SelectList(permissions, "PermissionID", "PermissionName", parentID);
            xvm.AddModelItem("Permissions", sl);
            return View("PermissionAddOrEdit", xvm);
        }
        public object PermissionRemove(Guid permissionID)
        {
            if (_permissionService.Remove(permissionID))
                return RedirectToAction("PermissionList");
            else
            {
                var prompt = new PromptViewModel("权限管理");
                prompt.AddMessage("删除失败，当前权限下有子权限！");

                var xvm = new XoohooViewModelItem<PromptViewModel>(prompt);
                return View("Prompt",xvm);
            }
        }
        public object PermissionMove(Guid permissionID, MovingTarget target)
        {
            _permissionService.Move(permissionID, target);

            return RedirectToAction("PermissionList");
        }
        [HttpPost]
        public object PermissionSave(PermissionInput permissionInput)
        {
            if (permissionInput == null)
                throw new ArgumentNullException("permissionInput");

            var prompt = new PromptViewModel("权限编辑");
            var xvm = new XoohooViewModelItem<PromptViewModel>(prompt);

            if (!TryValidateModel(permissionInput))
            {
                return View("PermissionAddOrEdit", new XoohooViewModelItem<PermissionInput>(permissionInput));
                //prompt.AddModelErrors(ModelState);
                //return View("Prompt", xvm);
            }

            ModelResult modelResult = _permissionService.Save(permissionInput);

            if (modelResult.IsValid)
            {
                return RedirectToAction("PermissionList");
            }
            else
            {
                prompt.AddModelErrors(modelResult.Errors);
                return View("Prompt",xvm);
            }

        }
#endif

        #endregion

        #region Private Methods

        private void ProjectPermissions(List<Permission> permissions)
        {
            if (permissions == null)
            {
                permissions = permissions ?? new List<Permission>();
                return;
            }
            string s = "　";

            foreach (var p in permissions)
            {
                if (p.PermissionLevel > 1)
                    p.PermissionName = s.Repeat(p.PermissionLevel - 1) + "┗ " + p.PermissionName;
            }
        }
        private void RemoveChildren(List<Permission> permissions, Guid permissionID)
        {
            if (permissions == null || permissionID == Guid.Empty) return;

            var children = (from p in permissions
                            where p.ParentID == permissionID
                            select p).ToList();

            permissions.RemoveAll(p => p.PermissionID == permissionID);

            for (int i = 0; i < children.Count; i++)
            {
                RemoveChildren(permissions, children[i].PermissionID);
            }

        }
        private void ProjectUserGroups(List<UserGroup> userGroups)
        {
            if (userGroups == null)
            {
                userGroups = userGroups ?? new List<UserGroup>();
                return; 
            }

            string s = "　";

            foreach (var p in userGroups)
            {
                if (p.UserGroupLevel > 1)
                    p.UserGroupName = s.Repeat(p.UserGroupLevel - 1) + "┗ " + p.UserGroupName;
            }
        }
        private void RemoveChildren(List<UserGroup> userGroups, Guid? userGroupID)
        {
            if (userGroups == null || userGroupID.IsNullOrEmpty()) return;

            var children = (from p in userGroups
                            where p.ParentID == userGroupID
                            select p).ToList();

            userGroups.RemoveAll(p => p.UserGroupID == userGroupID);

            for (int i = 0; i < children.Count; i++)
            {
                RemoveChildren(userGroups, children[i].UserGroupID);
            }

        }
        private void RemoveSystemUserGroup(List<UserGroup> userGroups)
        {
            userGroups.RemoveAll(p => p.IsSystem);
        }
        private object CreateUserSaveResult(ModelResult modelResult,string returnUrl)
        {
            if (modelResult.IsValid)
            {
                if (!String.IsNullOrEmpty(returnUrl))
                    return Redirect(returnUrl);
                else
                    return RedirectToAction("UserList");
            }
            else
            {
                var prompt = new PromptViewModel("用户编辑");
                prompt.AddModelErrors(modelResult.Errors);

                var xvm = new XoohooViewModelItem<PromptViewModel>(prompt);

                return View("Prompt",xvm);
            }
        }
        private List<UserGroup> CreateUserGroupTreeForAddOrEdit(Guid? currentID)
        {
            //获取用户组树
            var userGroups = _userGroupService.GetList();
            //去除当前节点的子树(包括当前节点)
            RemoveChildren(userGroups, currentID);
            //去除系统用户组(DisplayOrder为1和2)
            RemoveSystemUserGroup(userGroups);
            //格式化UserGroupName
            ProjectUserGroups(userGroups);
            return userGroups;
        }

        #endregion
    }
}
